<p>
  All stocks on NYSE and NASDAQ are used as the investment universe. We create a class to save all variables for each symbol.
</p>
<div class="section-example-container">
<pre class="python">
class SymbolData:
    def __init__(self, symbol):
        self.symbol = symbol
        self.window = RollingWindow[float](13)
        self.GARR_ratio = None
        self.yearly_return = None
</pre>
</div>
<p>
  To get the value for the above variables, we save the stock price at the start of each month in the rolling window for the last 12 months and calculate the monthly return and the yearly return.
  Then we can compute the last month's geometric average rate of return (GARR) and the previous 12-month GARR. The formulas are as follows
</P>
\[GARR_{last\ 12\ months}=(1+R_1)^{1/12}\cdot(1+R_2)^{1/12}\cdot\cdot\cdot(1+R_{11})^{1/12}\cdot(1+R_{12})^{1/12}-1\]
\[GARR_{last\ months}=(1+R_{last\ month})^{1/12}-1\]
</P>
<p>
  We assign the value of two returns to each symbol in <code>SymbolData</code> class. All stocks are sorted based on their past 12-month return.
  Stocks are then divided into 3 portfolios (top 30% - winner group, middle 40% and bottom 30% - loser group).  In the winner group, stocks are further
  classified into two categories: the return-increasing winner and return-decreasing winner using the ratio of last month's geometric average rate of return (GARR) over the last 12 month GARR.
</P>
\[GARR\ Ratio= \frac{GARR_{last\ months} }{GARR_{last\ 12\ months}}\]
<div class="section-example-container">
<pre class="python">
def CoarseSelectionFunction(self, coarse):
    if self.month_start:
        self.coarse = True
        coarse = [i for i in coarse if i.AdjustedPrice > 10]
        for i in coarse:
            if i.Symbol not in self.SymbolPrice:
                self.SymbolPrice[i.Symbol] = SymbolData(i.Symbol)
            self.SymbolPrice[i.Symbol].window.Add(float(i.AdjustedPrice))
            if self.SymbolPrice[i.Symbol].window.IsReady:
                price = np.array([i for i in self.SymbolPrice[i.Symbol].window])
                returns = (price[:-1]-price[1:])/price[1:]
                self.SymbolPrice[i.Symbol].yearly_return = (price[0]-price[-1])/price[-1]
                GARR_12 = np.prod([(1+i)**(1/12) for i in returns])-1
                GARR_1 = (1+returns[0])**(1/12)-1
                self.SymbolPrice[i.Symbol].GARR_ratio = GARR_1 / GARR_12
</pre>
</div>

<p>
  The decreasing-return winner group contains 13 stocks in winner group with the lowest GARR Ratio and vice-versa for the increasing-return winner group.
  The loser group is divided into the increasing-return loser and the decreasing-return loser groups using a similar methodology. The return-increasing loser group
  contains 15 stocks in loser group with the highest GARR Ratio.
</P>
<div class="section-example-container">
<pre class="python">
ReadySymbolPrice = {symbol: SymbolData for symbol, SymbolData in self.SymbolPrice.items() if SymbolData.window.IsReady}
if ReadySymbolPrice and len(ReadySymbolPrice)>50:
    # sort stocks in coarse by last 12-month return
    sorted_by_return = sorted(ReadySymbolPrice, key = lambda x: ReadySymbolPrice[x].yearly_return)
    # top 30% with the highest 12-month return goes into winner group
    winner = sorted_by_return[:int(len(sorted_by_return)*0.3)]
    # bottom 30% with the lowest 12-month return goes into loser group
    loser = sorted_by_return[-int(len(sorted_by_return)*0.3):]
    self.decrease_winner = sorted(winner, key = lambda x: ReadySymbolPrice[x].GARR_ratio)[:15]
    self.increase_loser = sorted(loser, key = lambda x: ReadySymbolPrice[x].GARR_ratio)[-15:]
    return self.decrease_winner+self.increase_loser
</pre>
</div>
<p>
The algorithm goes long stocks from the decreasing-return winner group and short stocks from the increasing-return loser group. The portfolio is created as equally weighted and rebalanced on a monthly basis.
</p>
<div class="section-example-container">
<pre class="python">
def OnData(self, data):
    if self.month_start and self.coarse:
        self.month_start = False
        self.coarse = False
        if all([self.decrease_winner, self.increase_loser]):
            stocks_invested = [x.Key for x in self.Portfolio]
            for i in stocks_invested:
                if i not in self.decrease_winner+self.increase_loser:
                    self.Liquidate(i)
            short_weight = 0.5/len(self.increase_loser)
            for j in self.increase_loser:
                self.SetHoldings(j, -short_weight)
            long_weight = 0.5/len(self.decrease_winner)
            for i in self.decrease_winner:
                self.SetHoldings(i, long_weight)
</pre>
</div>
